package com.nageoffer.jobtrain.common.framework.toolkit;

import cn.hutool.core.util.ArrayUtil;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Optional;

/**
 * SpEL表达式解析工具类
 */
public class SpELUtil {
    /**
     * 校验并返回实际使用的 spEL 表达式
     *
     * @param spEL spEL 表达式
     * @return 实际使用的 spEL 表达式
     */
    public static Object parseKey(String spEL, Method method, Object[] contextObject) {
        List<String> spELFlag = List.of("#", "T(");
        // 判断 spEL中是否含有 spELFlag标志
        Optional<String> optional = spELFlag.stream().filter(spELFlag::contains).findFirst();
        if (optional.isPresent()) {
            // 是否含有值
            return parse(spEL, method, contextObject);
        }
        return spEL;
    }

    /**
     * 转换参数为字符串
     *
     * @param spEL          spEl 表达式
     * @param contextObject 上下文对象
     * @return 解析的字符串值
     */
    public static Object parse(String spEL, Method method, Object[] contextObject) {
        // 获取参数的列表
        DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
        // 上下文环境
        StandardEvaluationContext context = new StandardEvaluationContext();
        SpelExpressionParser parser = new SpelExpressionParser();
        // 解析表达式
        Expression parsed = parser.parseExpression(spEL);
        // 获取到参数实际列表值
        String[] parameterNames = discoverer.getParameterNames(method);
        // 将获取到的参数列表设置进去到 context中
        if (ArrayUtil.isNotEmpty(parameterNames)) {
            for (int len = 0; len < parameterNames.length; len++) {
                context.setVariable(parameterNames[len], contextObject[len]);
            }
        }
        return parsed.getValue(context);
    }
}